#include "Parser.h"

void Parser::print(vector<Schedule*> d,OUTPUT_MESSAGE &O)
{
	string temp;
	for (int i=0;i<d.size();i++)
	{
		temp+=d[i]->get_day();
		temp+="\t";
		temp+=d[i]->get_start_time();
		temp+="\t";
		temp+=d[i]->get_end_time();
		temp+="\t";
		temp+=d[i]->get_name();
		temp+="\t";
		temp+=d[i]->get_place();
		temp+="\t";
		int j=0;
		switch (d[i]->get_priority())
		{

		case Schedule::LOW:
			j=1;
			break;
		case Schedule::NORMAL:
			j=2;
			break;
		case Schedule::HIGH:
			j=3;

		}
		for (int u=0;u<j;u++)
			temp+="*";
		O.output_strings.push_back(temp);
		temp.clear();
	}

}

OUTPUT_MESSAGE Parser::run(string input)
{
	OUTPUT_MESSAGE O;
	p_command.splitString(input);
	COMMAND command_type;	
	command_type=p_command.getCommandType();
	UNDO_BLOCK temp;
	int index;
	switch (command_type)
	{
	case ADD:
		if(p_command.generate_add())
		{
			
			List.add_schedule(&p_command.get_add_schedule());
			O.output_strings.push_back("event successfully added");
			temp.S=p_command.get_add_schedule();
			temp.type=DELETE;
			undo_stack.push(temp);
			
		}
		else
		{
			O.output_strings.push_back("add command format is wrong, please try again");
		}
		O.next_inputtype=ERROR;

		break;
	case DISPLAY:
		p_command.generate_display();
		print(List.search_schedule(p_command.get_event_term(),schedule_index,Schedule::NAME),O);
		O.next_inputtype=ERROR;
		break;
	case DELETE:
		if(p_command.generate_del())
		{
			O.output_strings.push_back("Choose the events you want to delete");
			print(List.search_schedule(p_command.get_event_term(),schedule_index,Schedule::NAME),O);
			O.next_inputtype=DELETE;
		}
		else
		{
			O.output_strings.push_back("delete command format is wrong, please try again");
			O.next_inputtype=ERROR;
		}
		break;
	case UPDATE:
		if (p_command.generate_update())
		{
			O.output_strings.push_back("Choose the events you want to update");
			print(List.search_schedule(p_command.get_event_term(),schedule_index,Schedule::NAME),O);
			O.next_inputtype=UPDATE;
		}
		else
		{
			O.output_strings.push_back("update command format is wrong, please try again");
			O.next_inputtype=ERROR;
		}
		break;
	case UNDO:
		if (undo_stack.empty())
		{
			O.output_strings.push_back("the undo stack is empty, undo operation cannot be executed");
			break;
		}
		else
		{
			UNDO_BLOCK temp;
			temp=undo_stack.top();
			switch(temp.type)
			{
			case ADD:
				List.add_schedule(&temp.S);
				undo_stack.pop();
				break;
			case DELETE:
				index=List.find_schedule_index(&temp.S);
				List.remove_schedule(index);
				undo_stack.pop();
				break;
			case UPDATE:
				 index=List.find_schedule_index(&temp.S);
				List.remove_schedule(index);
				undo_stack.pop();
				temp=undo_stack.top();
				List.add_schedule(&temp.S);
				undo_stack.pop();
				break;
			}
			O.output_strings.push_back("undo operation done");
		}
		break;
	case ERROR:
		O.output_strings.push_back("you have enter a wrong command please enter again");
		O.next_inputtype=ERROR;
		break;

	}


	return O;
}



OUTPUT_MESSAGE Parser::anotherinput(int choice,COMMAND anotherInputType)
{
	OUTPUT_MESSAGE O;
	UNDO_BLOCK undo_temp;
	switch (anotherInputType)
	{
	case UPDATE:
		{
			Schedule *temp;
			UPDATE_BLOCK U;
			temp=List.schedule_at_index(schedule_index[choice]);
			
			//pushing the schedule into undo
			undo_temp.S=*temp;
			undo_temp.type=UPDATE;
			undo_stack.push(undo_temp);
			/////////////////////////////////

			List.remove_schedule(schedule_index[choice]);
			U=p_command.get_update_block();
			switch (U.update_type)
			{
			case PLACE:
				temp->set_place(U.u_term);
				break;
			case TIME:
				temp->set_time(U.u_stime,U.u_etime);
				break;
			case EVENT:
				temp->set_name(U.u_term);
				break;
			case PRIORITY:
				temp->set_priority(U.level);
				break;
			case DAY:
				temp->set_day(U.u_term);
				break;

			}
			undo_temp.S=*temp;
			undo_temp.type=UPDATE;
			List.add_schedule(temp);
			break;
		}
		O.output_strings.push_back("update completed");
	case DELETE:
		{
			undo_temp.S=*List.schedule_at_index(schedule_index[choice]);
			undo_temp.type=ADD;
			List.remove_schedule(schedule_index[choice]);
		}
		break;
	}
	return O;
}

void Parser::init_storage(string fileName)
{
	List.init_filemanager(fileName);
}
